package com.gopay.common.util;

import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * 密码控件工具类
 * 
 * @PwdControlUtil.java
 * @author fanghw
 * @2013-5-8 下午2:52:52 www.gopay.com.cn Inc.All rights reserved.
 */
public class PwdControlUtil {
    // 日志
    private static final Logger log = Logger.getLogger(PwdControlUtil.class);

    // session中保存的uuid键名称
    public static final String PWD_CONTROL_UUID = "PwdControlUUID";
    
    //密码控件产生的密文固定长度
    private static int ENCRYPTED_PWD_LENGTH=256;

    /**
     * 生成密码控件的UUID随机数,并保存到session中
     * 
     * @param request
     * @return
     */
    public static synchronized String createUUID(HttpServletRequest request) {
        String uuid = createUUID();
        String keyUuid = createUUID();

        request.getSession().setAttribute(PWD_CONTROL_UUID + "@" + keyUuid, uuid);
        
        log.info("生成密码控件的UUID随机数--uuid="+request.getSession().getAttribute(PWD_CONTROL_UUID + "@" + keyUuid)
        		+",sessionId="+request.getSession().getId());
        
        return uuid + "@" + keyUuid;
    }
    
    public static synchronized String createUUID() {
    	// 生成随机数
    	String uuid = UUID.randomUUID().toString().replaceAll("@", "");
    	uuid = uuid.replaceAll("-", "0");
    	if (uuid.length() >= 32) {
    		uuid = uuid.substring(0, 32);
    	} else {
    		uuid += "0123456789abcdef0123456789abcdef".substring(0, 32 - uuid.length());
    	}
    	return uuid;
    }
    
    /**
     * 从密文和session中获取UUID
     * @param request
     * @param decryptTxt
     * @return
     * @throws Exception
     */
    public static synchronized String getUUIDFromPwdAndSession(HttpServletRequest request, String decryptTxt) throws Exception {
        String uuid = null;
        String pwdCtrlVersion = null;
        String ctrlID = null;
        
        // 新版本密码控件参数解析
        if (decryptTxt != null) {
            String[] loginPwdArr = decryptTxt.split("@");
            if (loginPwdArr != null && loginPwdArr.length >= 2) {
                pwdCtrlVersion = loginPwdArr[0];
                ctrlID = loginPwdArr[1];
                
            }
        }

        if ("2.0".equals(pwdCtrlVersion)) {// 2.0版本
            String key = PWD_CONTROL_UUID + "@" + ctrlID;
            
            uuid = (String) request.getSession().getAttribute(key);
            // 保证随机数只能被使用一次
            request.getSession().removeAttribute(key);
        }
        
        return uuid;
    }

    /**
     * 解密密码明文
     * 
     * @param request
     * @param decryptTxt
     * @return
     * @throws Exception
     */
    public static synchronized String decryptPwd(HttpServletRequest request, String decryptTxt) throws Exception {
        String pwd = null;

        String pwdCtrlVersion = null;
        String ctrlID = null;
        String encryptedPwd = null;

        log.info("密码控件2.0版本之请求参数密文=" + decryptTxt);

        // 新版本密码控件参数解析
        if (decryptTxt != null) {
            String[] loginPwdArr = decryptTxt.split("@");
            if (loginPwdArr != null && loginPwdArr.length >= 2) {
                pwdCtrlVersion = loginPwdArr[0];
                ctrlID = loginPwdArr[1];
                
                if(loginPwdArr.length==3){
                    encryptedPwd = loginPwdArr[2];
                }
                
            }
        }

        if ("2.0".equals(pwdCtrlVersion)) {// 2.0版本
            String key = PWD_CONTROL_UUID + "@" + ctrlID;
            
            if(encryptedPwd==null||encryptedPwd.length()!=ENCRYPTED_PWD_LENGTH){
                log.info("密码控件2.0版本之解密异常---密文长度不正确");
                throw new Exception("密码不能为空");
            }

            try {
                // RSA解密
                String source = RSAUtils.decryptRSA(encryptedPwd);
                String uuid = (String) request.getSession().getAttribute(key);
                if (uuid!=null&&!"".equals(uuid.trim()) && uuid.equals(source.substring(0, 32))) {
                    pwd = source.substring(32);
                }
            } catch (Exception e) {
                log.info("密码控件2.0版本之解密异常", e);
                throw new Exception("密码控件2.0版本解密异常", e);
            } finally {
                // 保证随机数只能被使用一次
                request.getSession().removeAttribute(key);
            }
        } else {// 1.0版本
            pwd = RSAUtils.decryptRSA(decryptTxt);
        }

        //log.info("密码控件2.0版本之解密后明文=" + pwd);
        return pwd;
    }
    
    public static synchronized String decryptPwd(String decryptTxt,String uuid) throws Exception {
    	String pwd = null;
    	String pwdCtrlVersion = null;
    	String encryptedPwd = null;
    	
    	// 新版本密码控件参数解析
    	if (decryptTxt != null) {
    		String[] loginPwdArr = decryptTxt.split("@");
    		if (loginPwdArr != null && loginPwdArr.length == 3) {
    			pwdCtrlVersion = loginPwdArr[0];
    			encryptedPwd = loginPwdArr[2];
    		}else if (loginPwdArr != null && loginPwdArr.length == 2) {
    			//临时解决cashier登陆问题 add by fanghw 20160312
    			pwdCtrlVersion = loginPwdArr[0];
    			encryptedPwd = loginPwdArr[1];
    		}
    	}
    	
    	if ("2.0".equals(pwdCtrlVersion)) {// 2.0版本
    		if(encryptedPwd==null||"".equals(encryptedPwd.trim())){
    			log.info("密码控件2.0版本之解密异常---密文为空");
    			throw new Exception("密码不能为空");
    		}
    		
    		try {
    			// RSA解密
    			String source = RSAUtils.decryptRSA(encryptedPwd);
    			if(StringUtils.isNotBlank(source) && source.length()>32){
    				String tmpUUID = source.substring(0, 32);
    				if(StringUtils.equals(uuid,tmpUUID)){
    					pwd = source.substring(32);
    				}
    			}
    		} catch (Exception e) {
    			log.info("密码控件2.0版本之解密异常", e);
    			throw new Exception("密码控件2.0版本解密异常", e);
    		} 
    	} else {// 1.0版本
    		pwd = RSAUtils.decryptRSA(decryptTxt);
    	}
    	//log.info("密码控件2.0版本之解密后明文=" + pwd);
    	return pwd;
    }
    
    /**
     * 指纹信息
     * @param s
     * @return
     */
    public static synchronized String finger(String s){
   	 byte[] baKeyword = new byte[s.length()/2];
   	  for(int i = 0; i < baKeyword.length; i++)
   	  {
   	   try
   	   {
   	   	 baKeyword[i] = (byte)(0xff & Integer.parseInt(s.substring(i*2, i*2+2),16));
   	   }
   	   catch(Exception e)
   	   {
   	    log.info("指纹信息异常",e);
   	   }
   	  }
   	  
   	 try 
   	 {
   	 	s = new String(baKeyword, "utf-8");//UTF-16le:Not
   	 } 
   	 catch (Exception e1) 
   	 {
   	  log.info("指纹信息异常",e1);
   	 } 
   	 return s;
   }


}
